# -*- coding: utf-8 -*-

'''
Created on 26/11/2011

@author: Luis M. Ugalde
www.forondarena.net

Copyright © 2011 Luis M. Ugalde
Licensed under the terms of the MIT License
(see LICENSE file for details)

This software can't be considered to be even in Alpha state. It still needs a lot of work.

Remember that abstract interfaces have a different syntax in python 3:
 You need the: from abc...
                class AbstractReader(metaclass = ABCMeta)
 and you dont need the __metaclass__ ...
'''


from abc import abstractmethod, ABCMeta
import zmq
from readers.readerexception import ReaderException


class AbstractReader(object):
    '''
    Generic class to be inherited by every reader implementation.
    Readers must implement all defined abstract methods. Raise TypeError otherwise
    '''


    __metaclass__ = ABCMeta


    def __init__(self, *args, **kwargs):
        self.context = zmq.Context()


    @abstractmethod
    def setSource(self, *args, **kwargs):
        pass


    @abstractmethod
    def connectSources(self, *args, **kwargs):
        pass


    @abstractmethod
    def closeSources(self, *args, **kwargs):
        pass


    def setBindReader(self, proto = "inproc", host = "reader", port = None):
        '''
        Set up a zeromq socket to send read lines to parsers
        '''

        port = str(port)
        self.readerbindaddress = proto + '://' + host + ':' + port if port else proto + '://' + host
        print "{}: Reader bind socket is {}".format(self.__class__.__name__, self.readerbindaddress) 
        
        
    def bindReader(self):
        '''
        Bind the defined zeromq socket
        '''
        
        try:
            self.readerbindsocket = self.context.socket(zmq.PUSH)
            self.readerbindsocket.bind(self.readerbindaddress)
        except zmq.ZMQBindError:
            tmperror = "Unable to bind " + self.readerbindaddress
            raise ReaderException(tmperror)


    def closeBindReader(self):
        '''
        Close the defined zeromq socket
        '''
        
        self.readerbindsocket.setsockopt(zmq.LINGER, 0)
        self.readerbindsocket.close()

    def setBindNotifyReader(self, proto = "inproc", host = "notifyreader", port = None):
        '''
        Set up a zeromq socket to broadcast notifications to parsers.
        '''
        
        port = str(port)
        self.readerbindnotifyaddress = proto + '://' + host + ':' + port if port else proto + '://' + host
        print "{}: Reader bind notify socket is {}".format(self.__class__.__name__, self.readerbindnotifyaddress) 
        
        
    def bindNotifyReader(self):
        '''
        Bind the defined zeromq socket
        '''

        try:
            self.readerbindnotifysocket = self.context.socket(zmq.PUB)
            self.readerbindnotifysocket.bind(self.readerbindnotifyaddress)
        except zmq.ZMQError:
            tmperror = "Unable to bind " + self.readerbindnotifyaddress
            raise ReaderException(tmperror)


    def closeBindNotifyReader(self):
        '''
        Close the defined zeromq socket
        '''
        
        self.readerbindnotifysocket.setsockopt(zmq.LINGER, 0)
        self.readerbindnotifysocket.close()


    def closeContext(self):
        self.context.term()
        

    @abstractmethod
    def getLines(self, *args, **kwargs):
        pass


if __name__ == '__main__':
    print "Please, do not run this"
